package com.hliushi.netty.server.handler;

import com.hliushi.netty.message.RpcRequestMessage;
import com.hliushi.netty.message.RpcResponseMessage;
import com.hliushi.netty.server.service.ServicesFactory;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author llhuang10
 * @date 2021/10/23 15:19
 */
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessage> {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        RpcRequestMessage message = new RpcRequestMessage(
                1,
                "com.hliushi.netty.server.service.HelloService",
                "sayHello",
                String.class,
                new Class[]{String.class},
                new Object[]{"张三"}
        );
        Object service = ServicesFactory.getService(Class.forName(message.getInterfaceName()));
        Method method = service.getClass().getMethod(message.getMethodName(), message.getParameterTypes());
        Object invoke = method.invoke(service, message.getParameterValue());
        System.out.println("invoke = " + invoke);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage message) {
        RpcResponseMessage response = new RpcResponseMessage();
        response.setSequenceId(message.getSequenceId());
        try {
            // HelloService service = (HelloService) ServicesFactory.getService(Class.forName(message.getInterfaceName()));
            Object service = ServicesFactory.getService(Class.forName(message.getInterfaceName()));
            Method method = service.getClass().getMethod(message.getMethodName(), message.getParameterTypes());
            Object invoke = method.invoke(service, message.getParameterValue());
            System.out.println(invoke);
            response.setReturnValue(invoke);
        } catch (InvocationTargetException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
            // Caused by: java.lang.ArithmeticException: / by zero
            String msg = "Caused by: " + e.toString() + ": " + e.getCause().getMessage();
            System.out.println(msg);
            // bug点: 当远程调用的方法出现异常时, 异常堆栈过长, 超出了黏包|半包处理器设置最大长度
            response.setExceptionValue(null);
            response.setExceptionMsg(msg);
        }
        ctx.writeAndFlush(response);
    }
}
